package com.example.permission.interceptor;

import com.example.permission.annotation.ApiPermission;
import com.example.permission.enums.PermissionType;
import com.example.permission.service.UserPermissionService;
import com.example.permission.util.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.lang.annotation.Annotation;


@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class ApiPermissionCheckAspect {

    private final UserPermissionService userPermissionService;

    @Around("@annotation(apiPermission)")
    public Object checkPermission(ProceedingJoinPoint joinPoint, ApiPermission apiPermission) throws Throwable {
        Long uid = UserContext.get();
        if (uid == null) {
            throw new SecurityException("用户未登录，拒绝访问");
        }

        String code = apiPermission.code();
        if (code == null || code.trim().isEmpty()) {
            code = resolveCodeFromMethod(joinPoint);
        }

        for (PermissionType required : apiPermission.permissions()) {
            boolean has = userPermissionService.hasPermission(uid, code, required.name());
            if (!has) {
                throw new SecurityException(String.format("权限不足，接口[%s]需要[%s]权限", code, required));
            }
        }

        return joinPoint.proceed();
    }

    private String resolveCodeFromMethod(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        RequestMapping mapping = signature.getMethod().getDeclaringClass().getAnnotation(RequestMapping.class);
        String base = (mapping != null && mapping.value().length > 0) ? mapping.value()[0] : "";
        String sub = "";

        for (Annotation ann : signature.getMethod().getAnnotations()) {
            if (ann instanceof GetMapping) {
                sub = ((GetMapping) ann).value()[0];
            } else if (ann instanceof PostMapping) {
                sub = ((PostMapping) ann).value()[0];
            } else if (ann instanceof PutMapping) {
                sub = ((PutMapping) ann).value()[0];
            } else if (ann instanceof DeleteMapping) {
                sub = ((DeleteMapping) ann).value()[0];
            } else if (ann instanceof RequestMapping) {
                sub = ((RequestMapping) ann).value()[0];
            }
        }

        return normalizePath(base + sub);
    }

    private String normalizePath(String path) {
        if (!path.startsWith("/")) {
            path = "/" + path;
        }
        return path.replaceAll("//+", "/");
    }
}
